package org.kenewstar.file.service.impl;

import org.kenewstar.common.bean.dto.FileAndFolderDto;
import org.kenewstar.common.bean.pojo.MicroFile;
import org.kenewstar.common.bean.pojo.MicroFolder;
import org.kenewstar.common.constant.CommonConstant;
import org.kenewstar.common.utils.CommonResult;
import org.kenewstar.common.utils.CommonUtil;
import org.kenewstar.file.dto.AddFolderDto;
import org.kenewstar.file.dto.FileShareDto;
import org.kenewstar.file.dto.FolderData;
import org.kenewstar.file.mapper.FileMapper;
import org.kenewstar.file.mapper.FolderMapper;
import org.kenewstar.file.service.FolderService;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author xinke.huang@hand-china.com
 * @version 1.0
 * @date 2021/2/28
 */
@Service
public class FolderServiceImpl implements FolderService {

    @Resource
    private FolderMapper folderMapper;
    @Resource
    private FileMapper fileMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<FileAndFolderDto> addFolder(AddFolderDto folder) {
        // 新增文件夹
        folderMapper.insertFolder(folder);
        // 查询当前文件夹下的文件及一级文件夹
        return folderMapper.selectFileAndFolderById(folder);
    }

    @Override
    public List<FileAndFolderDto> queryAllFileAndFolder(Integer uid, Long pid) {
        AddFolderDto dto = new AddFolderDto();
        dto.setUid(uid);
        dto.setPid(pid);
        return folderMapper.selectFileAndFolderById(dto);
    }

    @Override
    public List<FileAndFolderDto> queryDeletedFileAndFolder(Integer uid) {
        return folderMapper.selectDeletedFileAndFolderById(uid);
    }

    @Override
    public MicroFolder findFolderById(Long id) {
        return folderMapper.selectFolderById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchDeleteFolderAndFile(List<FileAndFolderDto> dtoList) {
        String deleted = "Y";
        List<FileAndFolderDto> fileList = new ArrayList<>();
        List<FileAndFolderDto> folderList = new ArrayList<>();
        for (FileAndFolderDto dto:dtoList){
            if (Objects.equals("file",dto.getType())){
                fileList.add(dto);
            } else {
                folderList.add(dto);
            }
        }
        // 修改文件夹
        if (folderList.size() !=0 ) {
            folderMapper.batchUpdateFolder(folderList, deleted);
        }
        if (fileList.size() != 0) {
            fileMapper.batchUpdateFile(fileList, deleted);
        }
        return 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int batchRefreshFolderAndFile(List<FileAndFolderDto> dtoList) {
        String deleted = "N";
        List<FileAndFolderDto> fileList = new ArrayList<>();
        List<FileAndFolderDto> folderList = new ArrayList<>();
        for (FileAndFolderDto dto:dtoList){
            if (Objects.equals("file",dto.getType())){
                fileList.add(dto);
            } else {
                folderList.add(dto);
            }
        }
        // 修改文件夹
        if (folderList.size() !=0 ) {
            folderMapper.batchUpdateFolder(folderList, deleted);
        }
        if (fileList.size() != 0) {
            fileMapper.batchUpdateFile(fileList, deleted);
        }
        return 1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int completeDeleteFileAndFolder(List<FileAndFolderDto> dtoList) {
        // 存放要删除的文件数据
        Set<Long> files = new HashSet<>();
        // 存放要删除的文件夹数据
        Set<Long> folders = new HashSet<>();
        // 遍历前端参数
        for (FileAndFolderDto dto : dtoList){
            if (Objects.equals(CommonConstant.FILE,dto.getType())){
                // 收集文件数据
                files.add(dto.getId());
            } else {
                // 收集文件夹数据
                folders.add(dto.getId());
                setFileAndFolder(files,folders,dto.getId());
            }
        }
        // 执行删除方法，进行批量删除
        if (files.size() != 0) {
            fileMapper.batchDeleteFile(files);
        }
        if (folders.size() != 0){
            folderMapper.batchDeleteFolder(folders);
        }
        return 1;
    }

    private void setFileAndFolder(Set<Long> files,Set<Long> folders,Long folderId){
        // 获取当前文件下的文件及文件夹
        List<Long> fileIds = fileMapper.selectFileIdByFid(folderId);
        files.addAll(fileIds);
        List<Long> folderIds = folderMapper.selectFolderIdByPid(folderId);
        folders.addAll(folderIds);
        for (Long pid : folderIds){
            setFileAndFolder(files,folders,pid);
        }
    }

    @Override
    public List<FileAndFolderDto> selectFileAndFolderByIds(List<FileShareDto> list) {
        List<FileShareDto> file = new ArrayList<>();
        List<FileShareDto> folder = new ArrayList<>();
        list.forEach(f -> {
            if (Objects.equals(f.getType(), CommonConstant.FILE)) {
                file.add(f);
            } else {
                folder.add(f);
            }
        });
        List<FileAndFolderDto> resultList = new ArrayList<>();
        if (folder.size() != 0) {
            resultList = folderMapper.selectFoldersById(folder);
        }
        if (file.size() != 0) {
            resultList.addAll(fileMapper.selectFilesById(file));
        }
        return resultList.stream().peek(f -> {
            if (Objects.equals(f.getType(), CommonConstant.FILE)) {
                f.setSize(CommonUtil.byte2Size(f.getFileByte()));
            } else {
                f.setSize("---");
            }
        }).collect(Collectors.toList());
    }

    @Override
    public List<FolderData> selectFolderData(Long folderId, Integer uid) {
        List<FolderData> folderDataList = folderMapper.selectFolderData(folderId, uid);
        return folderDataList.stream().map(folderData -> {
            long count = folderMapper.selectFolderCountByPid(folderData.getId());
            folderData.setIsChildren((int) count);
            if (count == 0) {
                folderData.setIsLeaf(true);
            }
            return folderData;
        }).collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult saveMoveFilesAndFolders(List<FileAndFolderDto> list, Long folderId) {
        for (FileAndFolderDto data: list) {
            TransactionStatus transactionStatus
                    = TransactionAspectSupport.currentTransactionStatus();
            try {
                if (Objects.equals(CommonConstant.FILE, data.getType())) {
                    fileMapper.updateFileFolderIdById(data.getId(), folderId);
                } else {
                    folderMapper.updateParentFolderIdById(data.getId(), folderId);
                }
            } catch (DataAccessException e) {
                // 回滚
                transactionStatus.setRollbackOnly();
                e.printStackTrace();
                return CommonResult.failed("文件夹或文件已存在");
            }
        }
        return CommonResult.success();
    }


    @Override
    public List<MicroFolder> selectFoldersByPid(Integer uid, Long pid) {
        return folderMapper.selectFoldersByPid(uid, pid);
    }
}
